package top.byfree.jbyan.saber.service

import org.ktorm.dsl.eq
import org.ktorm.dsl.limit
import org.ktorm.dsl.map
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import top.byfree.jbyan.saber.bean.F
import top.byfree.jbyan.saber.bean.Menus
import top.byfree.jbyan.saber.bean.ROOT_PARENT_ID
import top.byfree.jbyan.saber.bean.dto.FilterMenuDto
import top.byfree.jbyan.saber.bean.dto.MenuDto
import top.byfree.jbyan.saber.bean.dto.PageDto
import top.byfree.jbyan.saber.bean.pojo.Menu
import top.byfree.jbyan.saber.bean.vo.MenuVo
import top.byfree.jbyan.saber.bean.vo.RouteMenu
import top.byfree.jbyan.saber.common.AddGroup
import top.byfree.jbyan.saber.common.IdWorker
import top.byfree.jbyan.saber.dao.MenuDao

/**
 * 菜单业务处理层
 *
 * @author jbyan
 * @since 2024/5/15
 */
@Service
open class MenuService(
    @Autowired
    open val menusDao: MenuDao,
    @Autowired
    open val idWorker: IdWorker,
) {
    /**
     * 分页条件查询菜单列表
     *
     * TODO 有优化空间
     */
    fun page(size: Int = 10, current: Int, filterMenuDto: FilterMenuDto): PageDto<RouteMenu> {
        // 通过 size 和 current 计算 offset 值
        val offset = size * (current - 1)
        val query = menusDao.filter(filterMenuDto)
            .limit(offset, size)
        val map = menusDao.findAll().map { it.toRoute() }
        val menuVos = query.map(Menus::createEntity).map { it.toRoute() }
        val menuIds = menuVos.map { it.menuId }
        val rootMenus = menuVos.filter { it.parentId == ROOT_PARENT_ID || !menuIds.contains(it.parentId) }
        rootMenus.forEach { recurMenus(it, map) }

        return PageDto(rootMenus.sortedBy { it.menuId }, query.totalRecordsInAllPages, current, size)
    }

    /** 获取当前用户的权限路由菜单 */
    fun currentRouteMenus(): MutableList<RouteMenu> {
        val menus = menusDao.currentMenus().filter { it.status == 0 }.map(Menu::toRoute)
        // 获取所有的root菜单
        val rootMenus = menus.filter { it.parentId == ROOT_PARENT_ID }
        // 递归为所有route菜单子菜单赋值
        rootMenus.forEach { recurMenus(it, menus) }
        return rootMenus.toMutableList()
    }

    /** 工具方法：递归为目标菜单装载子菜单 */
    private fun recurMenus(current: RouteMenu, menus: List<RouteMenu>) {
        // 按钮下不会再有菜单
        if (current.menuType == F) {
            return
        }
        // 获取当前菜单的所有子菜单
        val children = menus.filter { it.parentId == current.menuId }

        // 子菜单不为空，递归为子菜单装载其子菜单
        if (children.isNotEmpty()) {
            children.forEach { recurMenus(it, menus) }
            current.children.addAll(children)
        }
    }

    /** 获取指定菜单详细信息 */
    fun getOne(menuId: String) = menusDao.findOne { it.menuId eq menuId }?.toVo()

    /** 修改指定菜单信息 */
    fun update(menuId: String, menuDto: MenuDto) = menusDao.update(menuDto.toMenu(menuId)) > 0
    /** 新增菜单 */
    fun add(menuDto: MenuDto) = menusDao.add(menuDto.toMenu(idWorker.nextId(), AddGroup::class.java)) > 0

}